﻿using System;
using System.Linq;
using System.Collections.Generic;
using ArithCollect;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Test2 {
    [TestClass]
    public class C1 {

    }
}
/*
 * 第一阶段：
    练经典常用算法，下面的每个算法给我打上十到二十遍，同时自己精简代码，
    因为太常用，所以要练到写时不用想，10-15分钟内打完，甚至关掉显示器都可以把程序打
    出来.  
     1.最短路(Floyd、Dijstra,BellmanFord)  
     2.最小生成树(先写个prim,kruscal要用并查集，不好写)  
     3.大数（高精度）加减乘除  
     4.二分查找. (代码可在五行以内)  
     5.叉乘、判线段相交、然后写个凸包.  
     6.BFS、DFS,同时熟练hash表(要熟，要灵活,代码要简)  
     7.数学上的有：辗转相除（两行内），线段交点、多角形面积公式.  
     8. 调用系统的qsort, 技巧很多，慢慢掌握.  
     9. 任意进制间的转换 
    
    第二阶段：
        练习复杂一点，但也较常用的算法。  
    如：  
     1. 二分图匹配（匈牙利），最小路径覆盖  
     2. 网络流，最小费用流。  
     3. 线段树.  
     4. 并查集。  
     5. 熟悉动态规划的各个典型：LCS、最长递增子串、三角剖分、记忆化dp  
     6.博弈类算法。博弈树，二进制法等。  
     7.最大团，最大独立集。  
     8.判断点在多边形内。  
     9. 差分约束系统.  
    10. 双向广度搜索、A*算法，最小耗散优先.
 */
namespace Test1 {
    [TestClass]
    public class T1 {
        [TestMethod]
        public void m11() {
            Floyd.main();
        }
    }
    public class Floyd {
        int[][] length = null;// 任意两点之间路径长度
        int[][][] path = null;// 任意两点之间的路径
        public Floyd(int[][] G) {
            int MAX = 100; int row = G.Length;// 图G的行数
            int[][] spot = new int[row][];// 定义任意两点之间经过的点
            int[] onePath = new int[row];// 记录一条路径
            length = new int[row][];
            path = new int[row][][];
            for (int i = 0; i < row; i++)// 处理图两点之间的路径
                for (int j = 0; j < row; j++) {
                    if (G[i][j] == 0) G[i][j] = MAX;// 没有路径的两个点之间的路径为默认最大
                    if (i == j) G[i][j] = 0;// 本身的路径长度为0
                }
            for (int i = 0; i < row; i++)// 初始化为任意两点之间没有路径
                for (int j = 0; j < row; j++)
                    spot[i][j] = -1;
            for (int i = 0; i < row; i++)// 假设任意两点之间的没有路径
                onePath[i] = -1;
            for (int v = 0; v < row; ++v)
                for (int w = 0; w < row; ++w)
                    length[v][w] = G[v][w];
            for (int u = 0; u < row; ++u)
                for (int v = 0; v < row; ++v)
                    for (int w = 0; w < row; ++w)
                        if (length[v][w] > length[v][u] + length[u][w]) {
                            length[v][w] = length[v][u] + length[u][w];// 如果存在更短路径则取更短路径
                            spot[v][w] = u;// 把经过的点加入
                        }
            for (int i = 0; i < row; i++) {// 求出所有的路径
                int[] point = new int[1];
                for (int j = 0; j < row; j++) {
                    point[0] = 0;
                    onePath[point[0]++] = i;
                    outputPath(spot, i, j, onePath, point);
                    path[i][j] = new int[point[0]];
                    for (int s = 0; s < point[0]; s++)
                        path[i][j][s] = onePath[s];
                }
            }
        }
        void outputPath(int[][] spot, int i, int j, int[] onePath, int[] point) {// 输出i// 到j// 的路径的实际代码，point[]记录一条路径的长度
            if (i == j) return;
            if (spot[i][j] == -1)
                onePath[point[0]++] = j;
            // System.out.print(" "+j+" ");
            else {
                outputPath(spot, i, spot[i][j], onePath, point);
                outputPath(spot, spot[i][j], j, onePath, point);
            }
        }
        public static void main() {
            var data = new int[][]{
                new []{ 0, 27, 44, 17, 11, 27, 42, 0, 0, 0, 20, 25, 21, 21, 18, 27, 0 },// x1
                new []{ 27, 0, 31, 27, 49, 0, 0, 0, 0, 0, 0, 0, 52, 21, 41, 0, 0 },// 1
                new []{ 44, 31, 0, 19, 0, 27, 32, 0, 0, 0, 47, 0, 0, 0, 32, 0, 0 },// 2
                new []{ 17, 27, 19, 0, 14, 0, 0, 0, 0, 0, 30, 0, 0, 0, 31, 0, 0 },// 3
                new []{ 11, 49, 0, 14, 0, 13, 20, 0, 0, 28, 15, 0, 0, 0, 15, 25, 30 },// 4
                new []{ 27, 0, 27, 0, 13, 0, 9, 21, 0, 26, 26, 0, 0, 0, 28, 29, 0 },// 5
                new []{ 42, 0, 32, 0, 20, 9, 0, 13, 0, 32, 0, 0, 0, 0, 0, 33, 0 },// 6
                new []{ 0, 0, 0, 0, 0, 21, 13, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0 },// 7
                new []{ 0, 0, 0, 0, 0, 0, 0, 19, 0, 11, 20, 0, 0, 0, 0, 33, 21 },// 8
                new []{ 0, 0, 0, 0, 28, 26, 32, 0, 11, 0, 10, 20, 0, 0, 29, 14, 13 },// 9
                new []{ 20, 0, 47, 30, 15, 26, 0, 0, 20, 10, 0, 18, 0, 0, 14, 9, 20 },// 10
                new []{ 25, 0, 0, 0, 0, 0, 0, 0, 0, 20, 18, 0, 23, 0, 0, 14, 0 },// 11
                new []{ 21, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 27, 22, 0, 0 },// 12
                new []{ 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 0 },// 13
                new []{ 18, 41, 32, 31, 15, 28, 0, 0, 0, 29, 14, 0, 22, 0, 0, 11, 0 },// 14
                new []{ 27, 0, 0, 0, 25, 29, 33, 0, 33, 14, 9, 14, 0, 0, 11, 0, 9 },// 15
                new []{ 0, 0, 0, 0, 30, 0, 0, 0, 21, 13, 20, 0, 0, 0, 0, 9, 0 } // 16
                                        };
            for (int i = 0; i < data.Length; i++) for (int j = i; j < data.Length; j++) if (data[i][j] != data[j][i])return; 
            Floyd test = new Floyd(data);
            for (int i = 0; i < data.Length; i++)
                for (int j = i; j < data[i].Length; j++) {
                    //System.out.println();
                    Console.WriteLine("From " + i + " to " + j + " path is: ");
                    for (int k = 0; k < test.path[i][j].Length; k++) {
                        Console.WriteLine(test.path[i][j][k] + " ");
                        Console.WriteLine();
                        Console.WriteLine("From " + i + " to " + j + " length :" + test.length[i][j]);
                    }
                }
        }
    }
}
